package i3.ui.option;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.DefaultListModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 *
 * @author  i30817
 */
public final class ColorOptions extends javax.swing.JPanel implements Iterable<Entry<String, Color>> {

    private boolean adjusting;

    /** Creates new form ColorOptions */
    public ColorOptions() {
        super();
        initComponents();
        colorList.addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) {
                    return;
                }

                colorSelectionChanged(e);
            }
        });
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new JScrollPane();
        colorList = new JList<String>(new DefaultListModel<String>());
        redLabel = new JLabel();
        greenLabel = new JLabel();
        blueLabel = new JLabel();
        redSlider = new JSlider();
        greenSlider = new JSlider();
        blueSlider = new JSlider();
        resetColor = new JButton();

        jScrollPane1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        colorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        jScrollPane1.setViewportView(colorList);

        redLabel.setText("Red  ");
        redLabel.setFocusable(false);

        greenLabel.setText("Green  ");
        greenLabel.setFocusable(false);

        blueLabel.setText("Blue  ");
        blueLabel.setFocusable(false);

        redSlider.setMaximum(255);
        redSlider.setValue(128);
        redSlider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent evt) {
                redSlidercolorChanged(evt);
            }
        });

        greenSlider.setMaximum(255);
        greenSlider.setValue(128);
        greenSlider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent evt) {
                greenSlidercolorChanged(evt);
            }
        });

        blueSlider.setMaximum(255);
        blueSlider.setValue(128);
        blueSlider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent evt) {
                blueSlidercolorChanged(evt);
            }
        });

        resetColor.setText("Reset to System color");
        resetColor.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                resetColorActionPerformed(evt);
            }
        });

        GroupLayout layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                .addGroup(layout.createParallelGroup(Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(50, 50, 50)
                        .addGroup(layout.createParallelGroup(Alignment.LEADING, false)
                            .addComponent(greenLabel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(blueLabel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(redLabel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(Alignment.LEADING)
                            .addComponent(redSlider, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 148, Short.MAX_VALUE)
                            .addComponent(blueSlider, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 148, Short.MAX_VALUE)
                            .addComponent(greenSlider, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 148, Short.MAX_VALUE))
                        .addGap(61, 61, 61))
                    .addGroup(layout.createSequentialGroup()
                        .addPreferredGap(ComponentPlacement.RELATED)
                        .addComponent(resetColor)
                        .addContainerGap())))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 255, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(41, 41, 41)
                        .addGroup(layout.createParallelGroup(Alignment.LEADING)
                            .addComponent(redSlider, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                            .addComponent(redLabel))
                        .addPreferredGap(ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(Alignment.LEADING)
                            .addComponent(greenSlider, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                            .addComponent(greenLabel))
                        .addPreferredGap(ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(blueSlider, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(ComponentPlacement.RELATED, 22, Short.MAX_VALUE)
                                .addComponent(resetColor))
                            .addComponent(blueLabel))))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void resetColorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetColorActionPerformed
        String name = colorList.getSelectedValue();
        Color defaultColor = defaultColorMap.get(name);
        Color oldColor = colorMap.get(name);

        adjusting = true;
        redSlider.setValue(defaultColor.getRed());
        greenSlider.setValue(defaultColor.getGreen());
        blueSlider.setValue(defaultColor.getBlue());
        adjusting = false;
        colorMap.put(name, defaultColor);

        firePropertyChange(name.toString(), oldColor, defaultColor);
    }//GEN-LAST:event_resetColorActionPerformed

    private void blueSlidercolorChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_blueSlidercolorChanged
        colorChanged();
    }//GEN-LAST:event_blueSlidercolorChanged

    private void greenSlidercolorChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_greenSlidercolorChanged
        colorChanged();
    }//GEN-LAST:event_greenSlidercolorChanged

    private void redSlidercolorChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_redSlidercolorChanged
        colorChanged();
    }//GEN-LAST:event_redSlidercolorChanged
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private JLabel blueLabel;
    private JSlider blueSlider;
    private JList<String> colorList;
    private JLabel greenLabel;
    private JSlider greenSlider;
    private JScrollPane jScrollPane1;
    private JLabel redLabel;
    private JSlider redSlider;
    private JButton resetColor;
    // End of variables declaration//GEN-END:variables
    private final Map<String, Color> colorMap = new HashMap<>();
    private final Map<String, Color> defaultColorMap = new HashMap<>();

    private void colorSelectionChanged(ListSelectionEvent e) {
        adjusting = true;
        Color c = colorMap.get(colorList.getSelectedValue());
        redSlider.setValue(c.getRed());
        greenSlider.setValue(c.getGreen());
        blueSlider.setValue(c.getBlue());
        adjusting = false;
    }

    private void colorChanged() {
        if (!adjusting) {
            int red = redSlider.getValue();
            int green = greenSlider.getValue();
            int blue = blueSlider.getValue();
            int alpha = 255; //alphaSlider.getValue();
            Color newColor = new Color(red, green, blue, alpha);
            Color oldColor = colorMap.get(colorList.getSelectedValue());
            colorMap.put(colorList.getSelectedValue(), newColor);
            firePropertyChange(colorList.getSelectedValue().toString(), oldColor, newColor);
        }
    }

    /**
     * Adds a color option. Always sends the current value and a old value of null
     * to registered listeners (it is supposted to be current, so it won't change if it really is,
     * and saves some code if it isn't).
     * @param name not null
     * @param current not null
     * @throws IllegalArgumentException in case the name or the color is null
     */
    public void addColorOption(String name, Color current, Color defaultColor) {
        if (name == null) {
            throw new IllegalArgumentException("Name color is null");
        }
        if (current == null) {
            throw new IllegalArgumentException("Current color is null");
        }
        if (defaultColor == null) {
            throw new IllegalArgumentException("Default color is null");
        }


        if (!colorMap.containsKey(name)) {
            DefaultListModel<String> mod = (DefaultListModel<String>) colorList.getModel();
            mod.addElement(name);
        }
        colorMap.put(name, current);
        defaultColorMap.put(name, defaultColor);
        //Always send the new value.
        firePropertyChange(name, null, current);
        if (colorList.getSelectedIndex() == -1) {
            colorList.setSelectedIndex(0);
        }
    }

    public Color get(String name) {
        return colorMap.get(name);
    }

    public void put(String name, Color c) {
        colorMap.put(name, c);
    }

    @Override
    public Iterator<Entry<String, Color>> iterator() {
        return colorMap.entrySet().iterator();
    }

    public void updateSize() {
        int width = 1;
        ListModel<String> m = colorList.getModel();
        ListCellRenderer<? super String> lcr = colorList.getCellRenderer();
        for (int i = 0; i < m.getSize(); i++) {
            String o = m.getElementAt(i);
            Component c = lcr.getListCellRendererComponent(colorList, o, 0, false, false);
            Dimension dim = c.getPreferredSize();
            width = Math.max(dim.width, width);
        }
        width = (int) (width + jScrollPane1.getVerticalScrollBar().getPreferredSize().getWidth());
        jScrollPane1.setPreferredSize(new Dimension(width, -1));
    }
}
